27장. Annotation
코드를 짜다 보면@Override, @Test 같은
골뱅이(@)가 붙은 표시를 보게 됩니다.
이것을 애너테이션(Annotation)이라고 합니다.
애너테이션은 코드에 붙이는 “표식“입니다.
코드의 동작을 직접 바꾸지는 않지만,
“이 코드는 이런 성격이다“라는 정보를 남깁니다.
비유하자면 이렇습니다.
애너테이션은 코드에 붙이는 “포스트잇“입니다.
내용물은 그대로지만,
보는 사람(또는 도구)에게 메모를 남깁니다.
스프링을 배우면@Controller, @Service 같은 애너테이션을
아주 많이 쓰게 됩니다.
그 기초를 여기서 다집니다.
27.1 Annotation 사용하기
애너테이션은 @와 이름으로 씁니다.
대상이 되는 코드 바로 앞에 붙입니다.
class Example {
@Deprecated("이제 newMethod()를 사용하세요")
fun oldMethod() {
println("옛날 방식")
}
fun newMethod() {
println("새 방식")
}
}
@Deprecated는 “이 코드는 이제 권장하지 않는다“는
표식입니다.
IDE는 이 표식을 보고oldMethod()에 취소선을 그어 줍니다.
이처럼 애너테이션은
사람과 도구에게 정보를 전달합니다.
27.2 Annotation 정의하기
애너테이션도 직접 만들 수 있습니다.annotation class로 선언합니다.
annotation class Loggable
이렇게 만든 애너테이션은
바로 붙여 쓸 수 있습니다.
@Loggable
fun processOrder() {
// ...
}
값을 담는 애너테이션도 만들 수 있습니다.
annotation class Role(val name: String)
@Role("ADMIN")
fun deleteUser() {
// ...
}
애너테이션이 담은 값은
나중에 리플렉션으로 읽습니다. (28장)
27.3 Target과 Retention
애너테이션을 정의할 때
두 가지 성질을 정할 수 있습니다.
첫째, Target입니다.
“이 애너테이션을 어디에 붙일 수 있는가“입니다.
@Target(AnnotationTarget.FUNCTION)
annotation class OnlyForFunction
AnnotationTarget.FUNCTION은
“함수에만 붙일 수 있다“는 뜻입니다.
클래스, 프로퍼티 등 다른 대상도 지정할 수 있습니다.
둘째, Retention입니다.
“이 애너테이션이 언제까지 남아 있는가“입니다.
| Retention | 의미 |
|---|---|
| SOURCE | 컴파일 후 사라짐 (도구/검사용) |
| BINARY | 클래스 파일에는 남지만 실행 시 못 읽음 |
| RUNTIME | 실행 중에도 읽을 수 있음 |
@Retention(AnnotationRetention.RUNTIME)
annotation class Loggable
실행 중에 리플렉션으로 읽으려면
반드시 RUNTIME이어야 합니다.
27.4 Kotlin의 Use-site Target
여기서 코틀린만의 특징이 나옵니다.
7장에서 배웠듯,
코틀린의 프로퍼티 하나는
사실 여러 요소로 이루어집니다.
- 뒤에서 값을 저장하는 필드(field)
- 값을 읽는 게터(getter)
- 값을 쓰는 세터(setter)
- 생성자 매개변수(parameter)
프로퍼티에 애너테이션을 붙이면
“이 중 어디에 붙일 것인가“가 문제가 됩니다.
그래서 코틀린은
붙일 위치를 콕 집어 줄 수 있게 했습니다.
이를 use-site target이라고 합니다.
class User(
@field:NotBlank val name: String, // 필드에
@get:JvmName("getEmail") val email: String // 게터에
)
주요 표식은 다음과 같습니다.
@field:: 필드에 붙임@get:: 게터에 붙임@set:: 세터에 붙임@param:: 생성자 매개변수에 붙임
27.5 DTO Validation을 예로 이해하기
이 개념이 실무에서 왜 중요한지
검증(Validation)을 예로 봅시다.
DTO의 값이 올바른지 검사할 때
애너테이션을 자주 씁니다. (DTO는 9장·33장 참고)
data class SignUpRequest(
@field:NotBlank
val name: String,
@field:Email
val email: String
)
여기서 @field:를 붙인 이유가 있습니다.
검증 라이브러리는 대개
객체의 “필드“를 검사합니다.
그래서 애너테이션이 필드에 붙어야
제대로 동작합니다.
만약 위치를 지정하지 않으면
애너테이션이 엉뚱한 곳(예: 생성자 매개변수)에만 붙어
검증이 동작하지 않을 수 있습니다.
이것이 바로
“자바와 다르게 동작하는 이유“입니다.
자바는 필드에 직접 애너테이션을 붙이지만,
코틀린은 프로퍼티가 여러 요소로 나뉘기 때문에
위치를 명시해 줘야 하는 것입니다.
코틀린에서 검증이 안 될 때는
@field:가 빠지지 않았는지 먼저 의심해 보세요.
27장을 마치며
이 장에서 우리는 다음을 배웠습니다.
- 애너테이션은 코드에 붙이는 표식이라는 점
annotation class로 직접 정의하는 법- Target(어디에)과 Retention(언제까지)의 의미
- 코틀린 프로퍼티는 여러 요소로 나뉘어 use-site target이 필요하다는 점
- DTO 검증에서
@field:가 중요한 이유
애너테이션이 담은 정보는
“리플렉션“으로 읽어야 실제로 활용됩니다.
다음 장에서 리플렉션을 배웁니다.